/*
 *  +----------------------------------------------------------------------
 *  | sophon [ A FAST GAME FRAMEWORK ]
 *  +----------------------------------------------------------------------
 *  | Copyright (c) 2023-2029 All rights reserved.
 *  +----------------------------------------------------------------------
 *  | Licensed ( http:www.apache.org/licenses/LICENSE-2.0 )
 *  +----------------------------------------------------------------------
 *  | Author: jqiris <1920624985@qq.com>
 *  +----------------------------------------------------------------------
 */

use std::fmt::Debug;
use std::str;

use anyhow::{anyhow, Result};
use prost::Message;
use serde::{de::DeserializeOwned, Serialize};

//序列化类型
pub enum SerializeType {
    SerializeNone,
    SerializeJson,
    SerializeProto,
}

pub trait ISerializer<T> {
    fn marshal(&self, msg: &T) -> Result<Vec<u8>>;
    fn unmarshal(&self, data: Vec<u8>) -> Result<T>;
}

#[derive(Debug, Default)]
pub struct ProtoSerializer {}

impl ProtoSerializer {
    pub fn new() -> ProtoSerializer {
        Self {}
    }
}

impl<T: Message + Default> ISerializer<T> for ProtoSerializer {
    fn marshal(&self, msg: &T) -> Result<Vec<u8>> {
        Ok(msg.encode_to_vec())
    }

    fn unmarshal(&self, data: Vec<u8>) -> Result<T> {
        match Message::decode(&*data) {
            Ok(v) => Ok(v),
            Err(err) => Err(anyhow!(err.to_string())),
        }
    }
}

unsafe impl Send for ProtoSerializer {}

unsafe impl Sync for ProtoSerializer {}

#[derive(Debug, Default)]
pub struct JsonSerializer {}

impl JsonSerializer {
    pub fn new() -> JsonSerializer {
        Self {}
    }
}

impl<T: Serialize + DeserializeOwned> ISerializer<T> for JsonSerializer {
    fn marshal(&self, msg: &T) -> Result<Vec<u8>> {
        Ok(serde_json::to_string(msg)?.into())
    }

    fn unmarshal(&self, data: Vec<u8>) -> Result<T> {
        let msg = str::from_utf8(&data)?.trim_matches(char::from(0));
        match serde_json::from_str(msg) {
            Ok(v) => Ok(v),
            Err(err) => Err(anyhow!(err.to_string())),
        }
    }
}

unsafe impl Send for JsonSerializer {}

unsafe impl Sync for JsonSerializer {}
